package values.avatar
{
import com.adobe.utils.DictionaryUtil;

import flash.errors.IllegalOperationError;
import flash.events.EventDispatcher;
import flash.utils.Dictionary;

import values.events.AvatarForceEvent;
import values.events.AvatarValueEvent;

[Event(name="hireHero", type="values.events.AvatarForceEvent")]
[Event(name="changeHeroState", type="values.events.AvatarForceEvent")]
[Event(name="addEquipment", type="values.events.AvatarValueEvent")]
[Event(name="removeEquipment", type="values.events.AvatarValueEvent")]
/**
 * AvatarForce
 * @author jliang
 *
 */
public class AvatarForce extends EventDispatcher
{
	//==========================================================================
	//  Constructor
	//==========================================================================
	public function AvatarForce()
	{
		super();
	}
	//==========================================================================
	//  Properties
	//==========================================================================
	protected var _player:PlayerAvatarValue;

	public function get player():PlayerAvatarValue
	{
		return _player;
	}
	
	/**
	 *  
	 * @return [ IAvatarValue ]
	 * 
	 */	
	public function get allHeros():Array
	{
		var list:Array = DictionaryUtil.getValues(fightGroup);
		list = list.concat(DictionaryUtil.getValues(idleGroup));
		list.sortOn("level", Array.NUMERIC);
		return [ player ].concat(list);
	}
	
	protected var fightGroup:Dictionary = new Dictionary(true);
	
	public function get fightAvatars():Array
	{
		var list:Array = DictionaryUtil.getValues(fightGroup);
		list.sortOn("level", Array.NUMERIC);
		return [ player ].concat(list);
	}
	
	public function get fightAvatarCount():int
	{
		return fightAvatars.length;
	}
	
	protected var idleGroup:Dictionary = new Dictionary(true);
	
	public function get idleAvatars():Array
	{
		var list:Array = DictionaryUtil.getValues(idleGroup);
		list.sortOn("level", Array.NUMERIC);
		return list;
	}
	
	public function get idleAvatarCount():int
	{
		return idleAvatars.length;
	}
	//==========================================================================
	//  Public methods
	//==========================================================================
	public function initialize(owner:Object, fights:Vector.<Object>, idles:Vector.<Object>):void
	{
		_player = new PlayerAvatarValue();
		player.initialize(owner.template, null, owner);
		player.party = 1;
		addHeroEventListener(player);
		
		var avo:IAvatarValue; 
		
		for each (var a1:Object in fights)
		{
			avo = AvatarValueFactory.createAvatarValue(a1.template.key , 1 , player.playerTechValue , a1);
			fightGroup[avo.key] = avo;
			addHeroEventListener(avo);
		}
		
		for each (var a2:Object in idles)
		{
			avo = AvatarValueFactory.createAvatarValue(a2.template.key , 1 , player.playerTechValue , a2);
			idleGroup[avo.key] = avo;
			addHeroEventListener(avo);
		}
	}
	
	public function dispose():void
	{
		if (player)
		{			
			removeHeroEventListener(player);
			player.dispose();
			_player = null;
		}
		
		if (fightGroup)
		{
			for each (var avo1:IAvatarValue in fightGroup)
			{
				removeHeroEventListener(avo1);
				avo1.dispose();
			}
			
			fightGroup = null;
		}
		
		if (idleGroup)
		{
			for each (var avo2:IAvatarValue in idleGroup)
			{
				removeHeroEventListener(avo2);
				avo2.dispose();
			}
			
			idleGroup = null;
		}
	}
	
	public function hire(avatarKey:String, params:* = null):void
	{
		var avatar:IAvatarValue = AvatarValueFactory.createAvatarValue(avatarKey , 1 ,  player.playerTechValue , params);
		fightGroup[avatar.key] = avatar;
		
		var evt:AvatarForceEvent = new AvatarForceEvent(AvatarForceEvent.HIRE_HERO);
		evt.params = { force:this, avatar:avatar };
		this.dispatchEvent(evt);
	}
	
	public function abandon(avatar:IAvatarValue):void
	{
		if (avatar != getAvatarByKey(avatar.key)) 
		{
			throw new IllegalOperationError("Cannot abandon a Hero who is not belong to the AvatarForce.");
			return;
		}
		
		if (idleGroup[avatar.key] != null) delete idleGroup[avatar.key];		
		else if (fightGroup[avatar.key] != null) delete fightGroup[avatar.key];
		
		var evt:AvatarForceEvent = new AvatarForceEvent(AvatarForceEvent.ABANDON_HERO);
		evt.params = { force:this, avatar:avatar };
		this.dispatchEvent(evt);
	}
	
	public function changeGroup(avatar:IAvatarValue):void
	{
		var state:int = 0;
		//判断是否是闲置状态
		if (idleGroup[avatar.key] != null)
		{
			delete idleGroup[avatar.key];
			fightGroup[avatar.key] = avatar;
			
			state = 1;
		}
		else
		{
			delete fightGroup[avatar.key];
			idleGroup[avatar.key] = avatar;
			
			state = 0;
		}
		
		var evt:AvatarForceEvent = new AvatarForceEvent(AvatarForceEvent.CHANGE_HERO_STATE);
		evt.params = { force:this, avatar:avatar, state:state };
		this.dispatchEvent(evt);
	}
	
	public function isIdleAvatar(avatar:IAvatarValue):Boolean
	{
		return idleGroup[avatar.key] != null;
	}
	
	public function getAvatarByKey(key:String):IAvatarValue
	{
		if (idleGroup[key] != null) return idleGroup[key];
		
		if (fightGroup[key] != null) return fightGroup[key];
		
		if (player.key == key) return player;
		
		return null;
	}
	//==========================================================================
	//  Protected methods
	//==========================================================================
	protected function addHeroEventListener(avatar:IAvatarValue):void
	{
		avatar.addEventListener(AvatarValueEvent.ADD_EQUIPMENT, changeEquipmentHandler);
		avatar.addEventListener(AvatarValueEvent.REMOVE_EQUIPMENT, changeEquipmentHandler);
	}
	
	protected function removeHeroEventListener(avatar:IAvatarValue):void
	{
		avatar.removeEventListener(AvatarValueEvent.ADD_EQUIPMENT, changeEquipmentHandler);
		avatar.removeEventListener(AvatarValueEvent.REMOVE_EQUIPMENT, changeEquipmentHandler);
	}
	
	protected function changeEquipmentHandler(event:AvatarValueEvent):void
	{
		var evt:AvatarValueEvent = new AvatarValueEvent(event.type);
		evt.params = event.params;
		this.dispatchEvent(evt);
	}
}
}




